package com.zf.poi.excel.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.poifs.filesystem.FileMagic;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * Excel工具
 */
@Slf4j
public class ExcelUtils {
    public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
    public static final String CONTENT_DISPOSITION = "Content-Disposition";

    public static final String XLS = "xls";
    public static final String XLSX = "xlsx";
    public static final Set<String> EXCEL_EXTENSION_SET = new HashSet<>(Arrays.asList(XLS, XLSX));


    /**
     * 导出时封装response,对中文编码以防乱码
     *
     * @param exportFileName 导出的文件名
     * @param response       响应对象
     */
    public static void decorateResponse(HttpServletResponse response, String exportFileName) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        // 这里URLEncoder.encode可以防止中文乱码
        String fileName = URLEncoder.encode(exportFileName, StandardCharsets.UTF_8.name())
                .replaceAll("\\+", "%20");
        // 暴露出 "Content-Disposition" 响应头，防止跨域获取不到
        response.setHeader(ACCESS_CONTROL_EXPOSE_HEADERS, CONTENT_DISPOSITION);
        // 暴露文件名
        response.setHeader(CONTENT_DISPOSITION, "attachment;filename*=utf-8''" + fileName + ".xlsx");
    }

    /**
     * 根据文件名获取扩展名
     *
     * @param fileName 文件名
     */
    public static String getExtensionByFilename(String fileName) {
        if (!StringUtils.hasText(fileName)) {
            return "";
        }
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    /**
     * 通过魔数(文件头)获取 excel 文件的真正扩展名
     * @param inputStream 文件流，需要支持 mark/reset 操作，如 BufferedInputStream
     */
    public static String getExtensionByFileMagic(InputStream inputStream) {
        try {
            FileMagic fileMagic = FileMagic.valueOf(inputStream);
            if (Objects.equals(fileMagic, FileMagic.OLE2)) {
                return XLS;
            } else if (Objects.equals(fileMagic, FileMagic.OOXML)) {
                return XLSX;
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return "";
    }

    /**
     * 通过魔数(文件头) 判断是否是 excel 文件
     * @param inputStream 文件流，需要支持 mark/reset 操作，如 BufferedInputStream
     */
    public static boolean isExcel(InputStream inputStream) {
        return EXCEL_EXTENSION_SET.contains(getExtensionByFileMagic(inputStream));
    }


    /**
     * 通过文件名判断是否是 excel 文件
     */
    public static boolean isExcel(String filename) {
        return EXCEL_EXTENSION_SET.contains(getExtensionByFilename(filename));
    }


}
